package com.whpost.api.controller.qyh;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.whpost.api.entity.OrgArrearsExcelDTO;
import com.whpost.api.entity.YqqfExcelDTO;
import com.whpost.api.utils.ApiUtils;
import com.whpost.service.entity.tools.ResultInfo;
import com.whpost.service.service.cwqf.QfkbApiServices;
import com.whpost.service.tools.ToolBean;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;

@RestController
@RequestMapping("/qyh/qfkb")
public class QfkbApiController {

    // 固定文件存储目录（请替换为实际服务器路径）
    private static final String FILE_STORAGE_DIR = "/home/cwqf/temp/";
    //private static final String FILE_STORAGE_DIR = "d://";
    // 访问域名前缀（根据实际部署的服务地址调整）
    private static final String BASE_DOWNLOAD_URL = "http://stjk.whsyzj.com/cwqf-api/qyh/qfkb/xls/";

    @Resource
    private QfkbApiServices qfkbApiServices;

    /**
     * 欠费看板首页
     * @return
     */
    @SaCheckLogin
    @RequestMapping(value ="/index_init")
    public ResultInfo index_init() {
        String loginId = ApiUtils.getLoginId();
        return qfkbApiServices.indexInit(loginId);
    }

    @SaCheckLogin
    @RequestMapping(value ="/jgkbInitData")
    public ResultInfo jgkbInitData(@RequestBody Map<String, Object> map) throws UnsupportedEncodingException {
        String loginId = ApiUtils.getLoginId();
        return qfkbApiServices.jgkbInitData(loginId,map);
    }

    @SaCheckLogin
    @RequestMapping(value ="/zykbInitData")
    public ResultInfo zykbInitData(@RequestBody Map<String, Object> map) throws UnsupportedEncodingException {
        String loginId = ApiUtils.getLoginId();
        return qfkbApiServices.zykbInitData(loginId,map);
    }

    @SaCheckLogin
    @RequestMapping(value ="/qskbInitData")//全市逾期欠费看板
    public ResultInfo qskbInitData(@RequestBody Map<String, Object> map) throws UnsupportedEncodingException {
        String loginId = ApiUtils.getLoginId();
        return qfkbApiServices.qskbInitData(loginId,map);
    }

    @SaCheckLogin
    @RequestMapping(value ="/qtwh_init")
    public ResultInfo qtwh_init() throws UnsupportedEncodingException {
        String loginId = ApiUtils.getLoginId();
        return qfkbApiServices.qtwhInit(loginId);
    }

    // 简单接收接口（仅打印参数，不生成实际Excel）
    @RequestMapping("/jgkb_xls")
    public ResponseEntity<Map<String, Object>> downloadExcel(
            @RequestParam("data") String dataStr) throws IOException {

        // 1. 创建存储目录（如果不存在）
        File storageDir = new File(FILE_STORAGE_DIR);
        if (!storageDir.exists()) {
            boolean mkdirsSuccess = storageDir.mkdirs();
            if (!mkdirsSuccess) {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("code", 500);
                errorResult.put("message", "创建文件存储目录失败");
                return ResponseEntity.status(500).body(errorResult);
            }
        }

        // 2. 解析前端传的 JSON 数据
        JSONObject dataObj = JSONObject.parseObject(dataStr);
        String token = dataObj.getString("token");
        JSONArray tableDataArray = dataObj.getJSONArray("tableData");

        // 3. 解析 tableData 为 Map 列表
        List<Map<String, Object>> tableDataMapList = JSON.parseObject(
                tableDataArray.toJSONString(),
                new TypeReference<List<Map<String, Object>>>() {}
        );

        // 4. 转换 Map 列表为 Excel 实体类列表
        List<OrgArrearsExcelDTO> excelDataList = new ArrayList<>();
        for (Map<String, Object> map : tableDataMapList) {
            OrgArrearsExcelDTO dto = new OrgArrearsExcelDTO();
            dto.setRank(map.get("排名") != null ? map.get("排名").toString() : "");
            dto.setUnit(map.get("单位") != null ? map.get("单位").toString() : "");
            dto.setAllArrears(map.get("综合欠费") != null ? map.get("综合欠费").toString() : "");
            dto.setAllOverdue(map.get("综合逾期") != null ? map.get("综合逾期").toString() : "");
            dto.setPostArrears(map.get("寄递欠费") != null ? map.get("寄递欠费").toString() : "");
            dto.setPostOverdue(map.get("寄递逾期") != null ? map.get("寄递逾期").toString() : "");
            dto.setBizArrears(map.get("邮务欠费") != null ? map.get("邮务欠费").toString() : "");
            dto.setBizOverdue(map.get("邮务逾期") != null ? map.get("邮务逾期").toString() : "");
            excelDataList.add(dto);
        }

        // 5. 打印接收日志
        System.out.println("接收的Token：" + token);
        System.out.println("生成Excel的数据条数：" + excelDataList.size());

        // 6. 生成文件名和文件路径
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String fileName = "机构看板_" + today + "_" + System.currentTimeMillis(); // 加时间戳避免重复
        String fileFullName = fileName + ".xlsx";
        String filePath = FILE_STORAGE_DIR + fileFullName;

        // 7. 写入Excel文件到固定目录
        EasyExcel.write(filePath, OrgArrearsExcelDTO.class)
                .sheet("机构欠费数据")
                .doWrite(excelDataList);

        // 8. 构建下载链接
        String downloadUrl = BASE_DOWNLOAD_URL + URLEncoder.encode(fileFullName, "UTF-8").replaceAll("\\+", "%20");

        // 9. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "文件生成成功");
        result.put("downloadUrl", downloadUrl); // 最终返回的链接
        result.put("fileName", fileFullName);

        return ResponseEntity.ok(result);
    }

    @RequestMapping("/yqkb_xls")
    public ResponseEntity<Map<String, Object>> downloadExcel1(
            @RequestParam("data") String dataStr) throws IOException {

        // 1. 创建存储目录（如果不存在）
        File storageDir = new File(FILE_STORAGE_DIR);
        if (!storageDir.exists()) {
            boolean mkdirsSuccess = storageDir.mkdirs();
            if (!mkdirsSuccess) {
                Map<String, Object> errorResult = new HashMap<>();
                errorResult.put("code", 500);
                errorResult.put("message", "创建文件存储目录失败");
                return ResponseEntity.status(500).body(errorResult);
            }
        }

        // 2. 解析前端传的 JSON 数据
        JSONObject dataObj = JSONObject.parseObject(dataStr);
        String token = dataObj.getString("token");
        JSONArray tableDataArray = dataObj.getJSONArray("tableData");

        // 3. 解析 tableData 为 Map 列表
        List<Map<String, Object>> tableDataMapList = JSON.parseObject(
                tableDataArray.toJSONString(),
                new TypeReference<List<Map<String, Object>>>() {}
        );

        // 4. 转换 Map 列表为 Excel 实体类列表
        List<YqqfExcelDTO> excelDataList = new ArrayList<>();
        for (Map<String, Object> map : tableDataMapList) {
            YqqfExcelDTO dto = new YqqfExcelDTO();
            dto.setRank(map.get("排名") != null ? map.get("排名").toString() : "");
            dto.setUnit(map.get("单位") != null ? map.get("单位").toString() : "");
            dto.setBk(map.get("报刊") != null ? map.get("报刊").toString() : "");
            dto.setFx(map.get("分销") != null ? map.get("分销").toString() : "");
            dto.setHj(map.get("函件") != null ? map.get("函件").toString() : "");
            dto.setJy(map.get("集邮") != null ? map.get("集邮").toString() : "");
            dto.setDs(map.get("电商") != null ? map.get("电商").toString() : "");
            dto.setGj(map.get("国际") != null ? map.get("国际").toString() : "");
            dto.setKdbg(map.get("快递包裹") != null ? map.get("快递包裹").toString() : "");
            dto.setBzkd(map.get("标准快递") != null ? map.get("标准快递").toString() : "");
            dto.setWl(map.get("物流") != null ? map.get("物流").toString() : "");
            dto.setTotal(map.get("合计") != null ? map.get("合计").toString() : "");
            excelDataList.add(dto);
        }

        // 5. 打印接收日志
        System.out.println("接收的Token：" + token);
        System.out.println("生成Excel的数据条数：" + excelDataList.size());

        // 6. 生成文件名和文件路径
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String fileName = "全市逾期欠费_" + today + "_" + System.currentTimeMillis(); // 加时间戳避免重复
        String fileFullName = fileName + ".xlsx";
        String filePath = FILE_STORAGE_DIR + fileFullName;

        // 7. 写入Excel文件到固定目录
        EasyExcel.write(filePath, YqqfExcelDTO.class)
                .sheet("全市逾期欠费数据")
                .doWrite(excelDataList);

        // 8. 构建下载链接
        String downloadUrl = BASE_DOWNLOAD_URL + URLEncoder.encode(fileFullName, "UTF-8").replaceAll("\\+", "%20");

        // 9. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "文件生成成功");
        result.put("downloadUrl", downloadUrl); // 最终返回的链接
        result.put("fileName", fileFullName);

        return ResponseEntity.ok(result);
    }

    @GetMapping("/xls/{fileName:.+}")
    public void downloadFile(@PathVariable String fileName, HttpServletResponse response) {
        try {
            // 1. 解码文件名 + 基础安全过滤（防路径遍历）
            String decodeFileName = URLDecoder.decode(fileName, "UTF-8");
            // 禁止包含 ../ 或 ..\ （简单有效防路径突破）
            if (decodeFileName.contains("../") || decodeFileName.contains("..\\")) {
                throw new RuntimeException("非法文件名！");
            }

            // 2. 拼接完整路径（固定目录+文件名）
            String filePath = FILE_STORAGE_DIR + decodeFileName;
            File file = new File(filePath);

            // 3. 校验文件存在+是文件
            if (!file.exists() || !file.isFile()) {
                throw new RuntimeException("文件不存在: " + filePath);
            }

            // 4. 你的下载逻辑（复用你给的代码）
            String downloadFileName = URLEncoder.encode(decodeFileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + downloadFileName + "\"");
            response.setContentType("application/octet-stream");

            // 5. 流读写（边读边写防OOM）
            try (FileInputStream inputStream = new FileInputStream(file);
                 OutputStream os = response.getOutputStream()) {
                byte[] bytes = new byte[1024];
                int readLength;
                while ((readLength = inputStream.read(bytes)) != -1) {
                    os.write(bytes, 0, readLength);
                }
                os.flush();
            }

        } catch (Exception e) {
            // 简单异常处理（按需调整）
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            try {
                response.getWriter().write("下载失败：" + e.getMessage());
            } catch (IOException ignored) {}
        }
    }

}
